use futures_util::try_join;
use sqlx::PgPool;
use crate::base::errors::AppError;
use crate::base::response::Pagination;
use crate::data::dto::user_dto::{CreateUserRequest, ModifyStatusRequest, UserInfoResponse, UserPageRequest};
use crate::data::model::user::User;
use crate::repository::menu_repository::MenuRepository;
use crate::repository::role_repository::RoleRepository;
use crate::repository::user_repository::UserRepository;

/// 用户服务，封装用户相关的数据库操作
///
/// **作者：** 张翔宇
/// **时间：** 2025年8月29日
pub struct UserService;

impl UserService {

    /// 添加新用户
    ///
    /// 处理用户创建的完整业务逻辑，包括：
    /// 1. 开启数据库事务确保操作原子性
    /// 2. 校验用户名唯一性
    /// 3. （注释中）预留手机号唯一性校验
    /// 4. 执行用户创建操作
    /// 5. 提交事务并返回结果
    ///
    /// # 参数
    /// * `db_pool` - 数据库连接池
    /// * `user_id` - 操作用户ID（创建者ID）
    /// * `data` - 包含新用户信息的请求DTO
    ///
    /// # 返回值
    /// 成功返回创建的用户模型，失败返回AppError
    pub async fn add_user(db_pool: &PgPool, user_id: &i64, data: CreateUserRequest) -> Result<User, AppError> {
        // 开启事务
        let mut tx = db_pool.begin()
            .await
            .map_err(|e| AppError::Runtime(format!("开启事务失败: {}", e)))?;

        // 查询用户名是否存在
        let username_exists = UserRepository::username_exists(db_pool, &data.username).await?;
        if username_exists {
            return Err(AppError::BadRequest("用户名已存在".to_string()));
        }

        // 查询手机号是否存在
        // let phone_exists = UserRepository::phone_exists(db_pool, &data.phone).await?;
        // if phone_exists {
        //     return Err(AppError::BadRequest("手机号已经存在".to_string()));
        // }

        let user = UserRepository::create_user(&mut tx, user_id, data).await?;

        // 提交事务
        tx.commit()
            .await
            .map_err(|e| AppError::Runtime(format!("创建用户事务提交失败: {}", e)))?;

        Ok(user)

    }

    /// 获取用户详细信息
    ///
    /// 查询指定用户的基本信息及其关联的角色和菜单权限
    /// 采用并行查询优化性能
    ///
    /// # 参数
    /// * `db_pool` - 数据库连接池
    /// * `user_id` - 要查询的用户ID
    ///
    /// # 返回值
    /// 成功返回包含用户信息、角色和菜单的响应DTO，失败返回AppError
    pub async fn info(db_pool: &PgPool, id: &i64) -> Result<UserInfoResponse, AppError> {
        // 根据ID查询用户信息
        let user = UserRepository::find_by_id(db_pool, id)
            .await?
            .ok_or(AppError::BadRequest("用户不存在".to_string()))?;

        // 查询角色与菜单
        // 采用并行查询，减少时间
        let (roles, menus) = try_join!(
            RoleRepository::find_auth_code_by_user_id(db_pool, id),
            MenuRepository::find_menu_code_by_user_id(db_pool, id)
        )?;

        // let res = UserInfoResponse::from(user);
        // res.roles = Some(roles);

        Ok(UserInfoResponse {
            roles: Some(roles),
            buttons: Some(menus),
            ..user.into()
        })
    }

    /// 分页查询用户列表
    ///
    /// 支持按分页参数查询用户列表并返回总数，用于前端分页展示
    ///
    /// # 参数
    /// * `db_pool` - 数据库连接池
    /// * `data` - 包含分页参数（页码、每页大小）的请求DTO
    ///
    /// # 返回值
    /// 成功返回包含分页信息和用户列表的响应DTO，失败返回AppError
    pub async fn page(db_pool: &PgPool, data: UserPageRequest) -> Result<Pagination<User>, AppError> {        
        let (users, total) = try_join!(
            UserRepository::page(db_pool, data.size, data.current, data.username.as_deref(), data.phone.as_deref()),
            UserRepository::total(db_pool, data.username.as_deref(), data.phone.as_deref())
        )?;

        Ok(Pagination::create(data.size, data.current, Some(total), users))
    }

    pub async fn modify_status(db_pool: &PgPool, data: &ModifyStatusRequest) -> Result<bool, AppError> {
        let result = UserRepository::update_is_active_by_user_id(db_pool, &data.id, &data.is_active.unwrap())
            .await
            .map_err(|e| AppError::Runtime(format!("修改用户状态失败: {:?}", e)))?;
        
        Ok(result)
    }

    pub async fn delete(db_pool: &PgPool, id: &i64) -> Result<(), AppError> {
        if UserRepository::delete_by_id(db_pool, id).await.is_err() {
            return Err(AppError::Database("删除用户失败".to_string()));
        }
        Ok(())
    }
}